#include <GL/glew.h>
#include <GL/glut.h>

#include <iostream>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <fstream>

#include "../headers/mesh.h"
#include "../headers/objloader.h"
#include "../headers/iluminacao.h"
#include "../headers/malhatextura.h"
#include "../headers/bezier.h"
#include "../headers/camera.h"
#include "../headers/peixeTeclado.h"
#include "../headers/shaders.h"
#include "../headers/beziPoint3d.h"

#define QNTOBJS 23

CCamera Camera[2];
Iluminacao luz1;
Mesh *obj[QNTOBJS];
PeixeTeclado tPeixe;
		
//global
int i;
float t1=0.001;
float t2=0.0005;
int tipoCamera=0;
int auxX = 0;
int auxY = 0;
//
using namespace std;

void key(unsigned char k, int x, int y)
{
	if( k == 'q' ) exit(0);

	switch (k) 
	{
		case 'q': exit(0);											case 'Q': exit(0);
		case '1': if(tipoCamera==0){tipoCamera=1;}else{tipoCamera=0;}
		case 'a': Camera[tipoCamera].StrafeRight(-2.0);  break;		case 'A': Camera[tipoCamera].StrafeRight(-2.0);  break;
		case 'd': Camera[tipoCamera].StrafeRight(2.0);   break;		case 'D': Camera[tipoCamera].StrafeRight(2.0);   break;
		case 'w': Camera[tipoCamera].MoveForward(-2.0 ); break;		case 'W': Camera[tipoCamera].MoveForward(-2.0 ); break;
		case 's': Camera[tipoCamera].MoveForward(2.0 );  break;		case 'S': Camera[tipoCamera].MoveForward(2.0 );  break;

	}
}

void mouse (int button, int state, int x, int y)
{
	auxX=x;
	auxY=y;
}

void motion (int x, int y) 
{
	if (auxX==0 && auxY==0){ auxX=x; auxY=y;}

	Camera[tipoCamera].RotateY(-(x-auxX)/3);
	Camera[tipoCamera].RotateX(-(y-auxY)/3);
	auxX=x;
	auxY=y;
}

void TeclasEspeciais(int tecla, int x, int y)
{
	switch(tecla)
	{
			case GLUT_KEY_UP :   {tPeixe.Anima(1); tPeixe.Colisao(); glutPostRedisplay(); break;} 	
			case GLUT_KEY_DOWN : {tPeixe.Anima(2); tPeixe.Colisao(); glutPostRedisplay(); break;}
			case GLUT_KEY_LEFT : {tPeixe.Anima(4);					 glutPostRedisplay(); break;}
			case GLUT_KEY_RIGHT :{tPeixe.Anima(3);					 glutPostRedisplay(); break;}
			default : {break;}
	}
}

void display(void)
{
	cout << tipoCamera;
	glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); 
	glLoadIdentity(); 
	Camera[tipoCamera].Render();

	glTranslatef(0,10,-50);

		GLfloat lightPos[] = { 0.0, 30.0, 50.0, 1.0 };
			glLightfv( GL_LIGHT0, GL_POSITION, lightPos );

	glColor4f(1,1,1,0);
	glScalef(0.6,0.5,0.5);
	glTranslatef(0,0,-50);

	for(i=1; i<QNTOBJS-8;i++)
	{
		obj[i]->drawMesh2();
	}
	glPushMatrix();
		tPeixe.desenhaPeixeTeclado();
		SF3dVector PosCam;

		if(tipoCamera==1)
		{
			cout<<tPeixe.dx<<endl;
			PosCam.x = tPeixe.dy;
			PosCam.y = 15;
			PosCam.z = tPeixe.dx+140;
			cout<<PosCam.z<<endl;
			glPushMatrix();
			Camera[tipoCamera].setPosicao(PosCam);
			glPopMatrix();
		}
		obj[22]->drawMesh2();
	glPopMatrix();

	t1=t1+0.001;
	t2=t2+0.0005;
	if(t1>=1)
		t1=0;
	if(t2>=1)
		t2=0;

	Bezier beziCardume1;
	beziCardume1.A.xx=0;   beziCardume1.B.xx=-103.0; beziCardume1.C.xx=-103.0; beziCardume1.D.xx=0;
	beziCardume1.A.yy=0;    beziCardume1.B.yy=20;    beziCardume1.C.yy=-10;   beziCardume1.D.yy=0;
	beziCardume1.A.zz=0;    beziCardume1.B.zz=-53.0; beziCardume1.C.zz=103.0;  beziCardume1.D.zz=0;
	Point3d coordCardume1 = beziCardume1.drawBezier (beziCardume1,t1);
	glPushMatrix();
		glColor4f(1,1,1,0);
		glTranslatef(coordCardume1.xx,coordCardume1.yy,coordCardume1.zz);
		glRotatef(sin(coordCardume1.xx),1,0,0);
		obj[16]->drawMesh2();
		glRotatef(sin(coordCardume1.xx)+0.01,1,0,0);
		obj[17]->drawMesh2();
		glRotatef(sin(coordCardume1.xx*0.000002),1,0,0);
		obj[18]->drawMesh2();
	glPopMatrix();

	Bezier beziCardume2;
	beziCardume2.A.xx=-40;  beziCardume2.B.xx=53.0; beziCardume2.C.xx=53.0;  beziCardume2.D.xx=-40;
	beziCardume2.A.yy=0;    beziCardume2.B.yy=10;   beziCardume2.C.yy=-10;   beziCardume2.D.yy=0;
	beziCardume2.A.zz=0;    beziCardume2.B.zz=83.0; beziCardume2.C.zz=-83.0; beziCardume2.D.zz=0;
	Point3d coordCardume2 = beziCardume2.drawBezier (beziCardume2,t2);
	glPushMatrix();
		glColor4f(1,1,1,0);
		glTranslatef(coordCardume2.xx,coordCardume2.yy,coordCardume2.zz);
		obj[19]->drawMesh2();
		obj[20]->drawMesh2();
		obj[21]->drawMesh2();
	glPopMatrix();	

    glUseProgram(0);

	glPushMatrix();
		glEnable(GL_BLEND);
		glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
		glColor4f(0.1,0.1,0.4,0.3);
		obj[23]->drawMesh2();
		glDisable(GL_BLEND);
	glPopMatrix();

	glUseProgram(p);

	glFlush(); 
	glutSwapBuffers();
	glutPostRedisplay();
}

void reshape(int width,int height)
{
	glViewport(0,0,width,height); 
	glMatrixMode(GL_PROJECTION); 
	glLoadIdentity(); 
	gluPerspective(45.0f,(float)1280/(float)800,0.1f,1000.0f);
	glMatrixMode(GL_MODELVIEW); 
	glLoadIdentity();
}

void init()
{
	luz1.setupRC();
	glClearColor(0.3,0.6,0.4,0);
	glClearDepth(1.0); 
	glDepthFunc(GL_LESS); 
	glEnable(GL_DEPTH_TEST); 
	glShadeModel(GL_SMOOTH); 

	glEnableClientState(GL_VERTEX_ARRAY);
	glEnableClientState(GL_NORMAL_ARRAY);
	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
	
//fog
	GLfloat density = 0.01;
	GLfloat fogColor[] = {0.8, 0.8, 0.9, 1};
	glFogfv(GL_FOG_COLOR, fogColor);
	glFogi(GL_FOG_MODE, GL_LINEAR);
	glFogf(GL_FOG_START, -100.0f);
	glFogf(GL_FOG_END, 100.0f);
	glEnable (GL_DEPTH_TEST); 
	glEnable (GL_FOG); 
	glFogi (GL_FOG_MODE, GL_EXP2); 
	glFogfv (GL_FOG_COLOR, fogColor); 
	glFogf (GL_FOG_DENSITY, density); 
	glHint (GL_FOG_HINT, GL_NICEST);
//

//carrega arquivos
	char nomeobj[30],str[30];;
	int n;

	ifstream ifs("modelos/modelos.txt", ios::in );
	if (ifs.fail())
    {
        cout << "Nao abriu o arquivo!" << endl;
        exit(1);
	}
	cout << "Abriu arquivo!" << endl;

	for(i=1; i<=QNTOBJS;i++)
	{
		ifs >> nomeobj;
		strcpy (str,"modelos/");
		strcat (str,nomeobj);
		cout << str << endl;

		obj[i]=ObjLoader::ReadMesh(str);
		obj[i]->initNeighbors();
		obj[i]->calcNormals();

		ifs >> nomeobj;
		strcpy (str,"modelos/");
		strcat (str,nomeobj);
		cout << str << endl;
		obj[i]->aplicaTextura(str);
	}
	setShaders();
}

int main(int argc, char *argv[])
{
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_RGB|GLUT_DOUBLE); 
	glutInitWindowSize(1280,800); 
	glutInitWindowPosition(0,0); 
	glutCreateWindow(" -- Aquario CG -- "); 

	init();

	glutDisplayFunc(display); 
	glutReshapeFunc(reshape); 
	glutKeyboardFunc(key); 
	glutMouseFunc(mouse); 
	glutMotionFunc(motion); 
	glutSpecialFunc(TeclasEspeciais);
	glutMainLoop(); 

	for(i=0;i<=QNTOBJS;i++)
	{
		delete obj[i];
	}
	return 0;
}








